{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %%writefile 1.py\n",
    "# 项目地址\n",
    "# https://easytrader.readthedocs.io/zh/master/usage/\n",
    "# 文档\n",
    "# https://easytrader.readthedocs.io/zh/master/usage/#3\n",
    "\n",
    "\n",
    "import jqktrader\n",
    "from jqktrader.log import logger\n",
    "\n",
    "user = jqktrader.use()\n",
    "\n",
    "user.connect(\n",
    "  exe_path=r'C:\\同花顺软件\\同花顺\\xiadan.exe',\n",
    "  tesseract_cmd=r'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "DEBUG:jqktrader:'close_pop_dialog' consume 0.0035 sec, cpu 0.0000 sec. args (), extra args {}\n",
      "DEBUG:jqktrader:'_switch_left_menus' consume 5.0054 sec, cpu 0.0000 sec. args (['查询[F4]', '资金股票'],), extra args {}\n"
     ]
    },
    {
     "ename": "ElementNotFoundError",
     "evalue": "{'control_id': 129, 'class_name': 'SysTreeView32', 'top_level_only': False, 'parent': <win32_element_info.HwndElementInfo - '', Internet Explorer_Hidden, 133566>, 'backend': 'win32'}",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTimeoutError\u001b[0m                              Traceback (most recent call last)",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\application.py:250\u001b[0m, in \u001b[0;36mWindowSpecification.__resolve_control\u001b[1;34m(self, criteria, timeout, retry_interval)\u001b[0m\n\u001b[0;32m    249\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 250\u001b[0m     ctrl \u001b[38;5;241m=\u001b[39m \u001b[43mwait_until_passes\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    251\u001b[0m \u001b[43m        \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    252\u001b[0m \u001b[43m        \u001b[49m\u001b[43mretry_interval\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    253\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__get_ctrl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    254\u001b[0m \u001b[43m        \u001b[49m\u001b[43m(\u001b[49m\u001b[43mfindwindows\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mElementNotFoundError\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    255\u001b[0m \u001b[43m         \u001b[49m\u001b[43mfindbestmatch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mMatchError\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    256\u001b[0m \u001b[43m         \u001b[49m\u001b[43mcontrols\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mInvalidWindowHandle\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    257\u001b[0m \u001b[43m         \u001b[49m\u001b[43mcontrols\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mInvalidElement\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    258\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcriteria\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    260\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTimeoutError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\timings.py:458\u001b[0m, in \u001b[0;36mwait_until_passes\u001b[1;34m(timeout, retry_interval, func, exceptions, *args, **kwargs)\u001b[0m\n\u001b[0;32m    457\u001b[0m             err\u001b[38;5;241m.\u001b[39moriginal_exception \u001b[38;5;241m=\u001b[39m e\n\u001b[1;32m--> 458\u001b[0m             \u001b[38;5;28;01mraise\u001b[39;00m err\n\u001b[0;32m    460\u001b[0m \u001b[38;5;66;03m# return the function value\u001b[39;00m\n",
      "\u001b[1;31mTimeoutError\u001b[0m: ",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[1;31mElementNotFoundError\u001b[0m                      Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[3], line 3\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 7-29日待测试\u001b[39;00m\n\u001b[0;32m      2\u001b[0m \u001b[38;5;66;03m# 获取资金状况\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m \u001b[43muser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbalance\u001b[49m\n\u001b[0;32m      4\u001b[0m \u001b[38;5;66;03m# 获取持仓\u001b[39;00m\n\u001b[0;32m      5\u001b[0m user\u001b[38;5;241m.\u001b[39mposition\n",
      "File \u001b[1;32mE:\\jqktrader-main\\jqktrader\\clienttrader.py:132\u001b[0m, in \u001b[0;36mClientTrader.balance\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    130\u001b[0m \u001b[38;5;129m@property\u001b[39m\n\u001b[0;32m    131\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mbalance\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m--> 132\u001b[0m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_switch_left_menus\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m查询[F4]\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m资金股票\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    134\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_balance_from_statics()\n",
      "File \u001b[1;32mE:\\jqktrader-main\\jqktrader\\utils\\perf.py:43\u001b[0m, in \u001b[0;36mperf_clock.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m     32\u001b[0m logger\u001b[38;5;241m.\u001b[39mdebug(\n\u001b[0;32m     33\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m consume \u001b[39m\u001b[38;5;132;01m%2.4f\u001b[39;00m\u001b[38;5;124m sec, cpu \u001b[39m\u001b[38;5;132;01m%2.4f\u001b[39;00m\u001b[38;5;124m sec. args \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m, extra args \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m     34\u001b[0m     \u001b[38;5;241m%\u001b[39m (\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m     40\u001b[0m     )\n\u001b[0;32m     41\u001b[0m )\n\u001b[0;32m     42\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ex \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m---> 43\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m ex\n\u001b[0;32m     44\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m result\n",
      "File \u001b[1;32mE:\\jqktrader-main\\jqktrader\\utils\\perf.py:26\u001b[0m, in \u001b[0;36mperf_clock.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m     23\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m     25\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 26\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[43mf\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     27\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m ex1:\n\u001b[0;32m     28\u001b[0m     ex \u001b[38;5;241m=\u001b[39m ex1\n",
      "File \u001b[1;32mE:\\jqktrader-main\\jqktrader\\clienttrader.py:527\u001b[0m, in \u001b[0;36mClientTrader._switch_left_menus\u001b[1;34m(self, path, sleep)\u001b[0m\n\u001b[0;32m    524\u001b[0m \u001b[38;5;129m@perf_clock\u001b[39m\n\u001b[0;32m    525\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21m_switch_left_menus\u001b[39m(\u001b[38;5;28mself\u001b[39m, path, sleep\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0.2\u001b[39m):\n\u001b[0;32m    526\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclose_pop_dialog()\n\u001b[1;32m--> 527\u001b[0m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_left_menus_handle\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_item\u001b[49m(path)\u001b[38;5;241m.\u001b[39mselect()\n\u001b[0;32m    528\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_app\u001b[38;5;241m.\u001b[39mtop_window()\u001b[38;5;241m.\u001b[39mtype_keys(\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{F5}\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m    529\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mwait(sleep)\n",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\application.py:379\u001b[0m, in \u001b[0;36mWindowSpecification.__getattribute__\u001b[1;34m(self, attr_name)\u001b[0m\n\u001b[0;32m    374\u001b[0m \u001b[38;5;66;03m# if we already have 2 levels of criteria (dlg, control)\u001b[39;00m\n\u001b[0;32m    375\u001b[0m \u001b[38;5;66;03m# this third must be an attribute so resolve and get the\u001b[39;00m\n\u001b[0;32m    376\u001b[0m \u001b[38;5;66;03m# attribute and return it\u001b[39;00m\n\u001b[0;32m    377\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcriteria) \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m2\u001b[39m:  \u001b[38;5;66;03m# FIXME - this is surprising\u001b[39;00m\n\u001b[1;32m--> 379\u001b[0m     ctrls \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__resolve_control\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcriteria\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    381\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m    382\u001b[0m         \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(ctrls[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m], attr_name)\n",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\application.py:261\u001b[0m, in \u001b[0;36mWindowSpecification.__resolve_control\u001b[1;34m(self, criteria, timeout, retry_interval)\u001b[0m\n\u001b[0;32m    250\u001b[0m     ctrl \u001b[38;5;241m=\u001b[39m wait_until_passes(\n\u001b[0;32m    251\u001b[0m         timeout,\n\u001b[0;32m    252\u001b[0m         retry_interval,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    257\u001b[0m          controls\u001b[38;5;241m.\u001b[39mInvalidElement),\n\u001b[0;32m    258\u001b[0m         criteria)\n\u001b[0;32m    260\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTimeoutError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m--> 261\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m e\u001b[38;5;241m.\u001b[39moriginal_exception\n\u001b[0;32m    263\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m ctrl\n",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\timings.py:436\u001b[0m, in \u001b[0;36mwait_until_passes\u001b[1;34m(timeout, retry_interval, func, exceptions, *args, **kwargs)\u001b[0m\n\u001b[0;32m    433\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m    434\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m    435\u001b[0m         \u001b[38;5;66;03m# Call the function with any arguments\u001b[39;00m\n\u001b[1;32m--> 436\u001b[0m         func_val \u001b[38;5;241m=\u001b[39m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    438\u001b[0m         \u001b[38;5;66;03m# if no exception is raised then we are finished\u001b[39;00m\n\u001b[0;32m    439\u001b[0m         \u001b[38;5;28;01mbreak\u001b[39;00m\n",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\application.py:222\u001b[0m, in \u001b[0;36mWindowSpecification.__get_ctrl\u001b[1;34m(self, criteria_)\u001b[0m\n\u001b[0;32m    220\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbackend\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m ctrl_criteria:\n\u001b[0;32m    221\u001b[0m     ctrl_criteria[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mbackend\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbackend\u001b[38;5;241m.\u001b[39mname\n\u001b[1;32m--> 222\u001b[0m ctrl \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbackend\u001b[38;5;241m.\u001b[39mgeneric_wrapper_class(\u001b[43mfindwindows\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfind_element\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mctrl_criteria\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[0;32m    223\u001b[0m previous_parent \u001b[38;5;241m=\u001b[39m ctrl\u001b[38;5;241m.\u001b[39melement_info\n\u001b[0;32m    224\u001b[0m ctrls\u001b[38;5;241m.\u001b[39mappend(ctrl)\n",
      "File \u001b[1;32mC:\\anaconda3\\envs\\ths_jy\\Lib\\site-packages\\pywinauto\\findwindows.py:87\u001b[0m, in \u001b[0;36mfind_element\u001b[1;34m(**kwargs)\u001b[0m\n\u001b[0;32m     84\u001b[0m elements \u001b[38;5;241m=\u001b[39m find_elements(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m     86\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m elements:\n\u001b[1;32m---> 87\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m ElementNotFoundError(kwargs)\n\u001b[0;32m     89\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(elements) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[0;32m     90\u001b[0m     exception \u001b[38;5;241m=\u001b[39m ElementAmbiguousError(\n\u001b[0;32m     91\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThere are \u001b[39m\u001b[38;5;132;01m{0}\u001b[39;00m\u001b[38;5;124m elements that match the criteria \u001b[39m\u001b[38;5;132;01m{1}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(\n\u001b[0;32m     92\u001b[0m             \u001b[38;5;28mlen\u001b[39m(elements),\n\u001b[0;32m     93\u001b[0m             six\u001b[38;5;241m.\u001b[39mtext_type(kwargs),\n\u001b[0;32m     94\u001b[0m         )\n\u001b[0;32m     95\u001b[0m     )\n",
      "\u001b[1;31mElementNotFoundError\u001b[0m: {'control_id': 129, 'class_name': 'SysTreeView32', 'top_level_only': False, 'parent': <win32_element_info.HwndElementInfo - '', Internet Explorer_Hidden, 133566>, 'backend': 'win32'}"
     ]
    }
   ],
   "source": [
    "# 7-29日待测试\n",
    "# 获取资金状况\n",
    "user.balance\n",
    "# 获取持仓\n",
    "user.position"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 7-29日待测试\n",
    "user.buy('601238', price=7.74, amount=100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 7-29日待测试\n",
    "# 获取持仓\n",
    "user.position"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取资金状况\n",
    "user.balance\n",
    "# 获取持仓\n",
    "user.position\n",
    "# 查询委托\n",
    "user.today_entrusts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 买入\n",
    "user.buy('162411', price=0.55, amount=100)\n",
    "# 卖出\n",
    "user.sell('162411', price=0.55, amount=100)\n",
    "# 撤单\n",
    "user.cancel_entrust('buy/sell 获取的 entrust_no')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = user.buy('000878', price=12.45, amount=100)\n",
    "# {'entrust_no': '4723950167'}\n",
    "a\n",
    "user.cancel_entrust(a['entrust_no'])\n",
    "# {'message': 'success'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "import flask\n",
    "import json\n",
    "\n",
    "app = flask.Flask(__name__)\n",
    "\n",
    "@app.route('/buy', methods=['POST'])\n",
    "def buy():\n",
    "  # 获取请求参数\n",
    "  code = flask.request.form.get('code')\n",
    "  price = flask.request.form.get('price')\n",
    "  amount = flask.request.form.get('amount')\n",
    "  logger.info(\"flask收到请求：{}\".format(json.dumps({'code': code, 'price': price, 'amount': amount})))\n",
    "  # 调用买入函数，返回订单id\n",
    "  entrust_no = user.buy(code, price, amount)\n",
    "  logger.info(\"订单id：{}\".format(entrust_no))\n",
    "  return entrust_no\n",
    "\n",
    "@app.route('/sell', methods=['POST'])\n",
    "def sell():\n",
    "  # 获取请求参数\n",
    "  code = flask.request.form.get('code')\n",
    "  price = flask.request.form.get('price')\n",
    "  amount = flask.request.form.get('amount')\n",
    "  logger.info(\"flask收到请求：{}\".format(json.dumps({'code': code, 'price': price, 'amount': amount})))\n",
    "  # 调用卖出函数\n",
    "  return user.sell(code, price, amount)\n",
    "\n",
    "@app.route('/cancel', methods=['POST'])\n",
    "def cancel():\n",
    "  # 获取请求参数\n",
    "  entrust_no = flask.request.form.get('entrust_no')\n",
    "  logger.info(\"flask收到请求：{}\".format(json.dumps({'entrust_no': entrust_no})))\n",
    "  # 调用撤单函数\n",
    "  return user.cancel_entrust(entrust_no)\n",
    "\n",
    "if __name__ == '__main__':\n",
    "  app.run(host='0.0.0.0', port=6030)\n",
    "# 运行这个demo\n",
    "\n",
    "# 单元测试\n",
    "# curl -X POST -d \"code=000878&price=12.45&amount=100\" http://192.168.5.7:6030/buy\n",
    "# curl -X POST -d \"entrust_no=4723953366\" http://192.168.5.7:6030/cancel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (ths_jy)",
   "language": "python",
   "name": "ths_jy"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
